﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Steema.TeeChart;
using Steema.TeeChart.Tools;
using AAA.Meta.Chart.Data;
using AAA.TeeChart.Data;
using AAA.Meta.Chart;
using AAA.ResultSet;
using AAA.DesignPattern.Observer;
using AAA.Base.Util.Hook;
using AAA.Forms.Components;
using AAA.Forms.Components.MetaData;
using AAA.Base.Util;
using System.Drawing.Printing;

namespace AAA.TeeChart
{
    public partial class TeeChartPanel : UserControl, IObserver
    {
        [System.Runtime.InteropServices.DllImport("gdi32.dll")]
        public static extern long BitBlt(IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, int dwRop);

        private const string EMPTY_DATA = "NaN";
        private const int DEFAULT_BOTTOM_HEIGHT = 40;
        private Dictionary<string, TChart> _dicChart;
        private Dictionary<string, float> _dicChartSize;
        private Dictionary<string, TeeChartFormat> _dicChartFormat;
        private Dictionary<string, CursorTool> _dicHorizontalCursor;
        private Dictionary<string, CursorTool> _dicVerticalCursor;
        private Dictionary<string, List<string>> _dicSeries;
        private Dictionary<string, List<string>> _dicFieldName;
        private Dictionary<string, List<string>> _dicActiveSeries;
        private Dictionary<string, List<CursorTool>> _dicControlLine;
        private Dictionary<string, List<float>> _dicControlLineValue;
        private Dictionary<string, BarDataExtra> _dicExtraInfo;
        private Dictionary<string, List<string>> _dicActiveExtraInfo;        
        private List<string> _lstFieldName;
        private List<string> _lstChartName;
        private Dictionary<string, RichTextLabel> _dicChartLabel;
        private Dictionary<string, LabelAlignmentEnum> _dicChartLabelAlignment;

        private string _strDateTimeFormat;
        private bool _isChangeCursorPosition;

        private int _iTotalPointCount;
        private int _iPointPerPage;
        private int _iDefaultPointPerPage = 100;

        private bool _isShowHorizontalCursor;
        private bool _isShowVerticalCursor;

        private bool _isShowInfoTable;
        private bool _isShowScale;
        private bool _isShowLightPane;

        private int _iCurrentPoint;

        private KeyboardHook _keyboardHook;
        public event PositionChangeEventHandler OnPositionChange;

        private string _strBaseSeriesName = "";
        private BarData _baseSeriesData;

        private Bitmap _memoryImage = null;

        public string BaseSeriesName
        {
            get { return _strBaseSeriesName; }
            set { _strBaseSeriesName = value; }
        }

        public TeeChartPanel()
        {
            InitializeComponent();

            _dicChart = new Dictionary<string, TChart>();
            _dicChartFormat = new Dictionary<string, TeeChartFormat>();
            _dicChartSize = new Dictionary<string, float>();
            _dicHorizontalCursor = new Dictionary<string, CursorTool>();
            _dicVerticalCursor = new Dictionary<string, CursorTool>();
            _dicSeries = new Dictionary<string, List<string>>();
            _dicFieldName = new Dictionary<string, List<string>>();
            _lstChartName = new List<string>();
            _dicControlLine = new Dictionary<string, List<CursorTool>>();
            _dicControlLineValue = new Dictionary<string, List<float>>();
            _dicActiveSeries = new Dictionary<string, List<string>>();
            _dicExtraInfo = new Dictionary<string, BarDataExtra>();            
            _dicActiveExtraInfo = new Dictionary<string, List<string>>();
            _dicChartLabel = new Dictionary<string, RichTextLabel>();
            _dicChartLabelAlignment = new Dictionary<string, LabelAlignmentEnum>();
            tblInfo.Columns.Add("Field", "名稱");
            tblInfo.Columns.Add("Value", "數值");
            _isChangeCursorPosition = true;
            
            MessageSubject.Instance().Subject.Attach(this);
            
        }

        public void ScrollToMax()
        {
            SeriesFormat seriesFormat;
            TeeChartFormat chartFormat;
            BarData barData;
            List<string> lstSeries;
            int iPoint = 0;

            try
            {
                datetimeScroll.Value = datetimeScroll.Maximum;

                foreach (string strChart in _dicActiveSeries.Keys)
                {
                    lstSeries = _dicActiveSeries[strChart];
                    chartFormat = _dicChartFormat[strChart];

                    foreach (string strSeries in lstSeries)
                    {
                        seriesFormat = chartFormat.GetSeriesFormat(strSeries);
                        barData = chartFormat.DataSource.GetBarData(strSeries);

                        iPoint = Math.Max(barData.GetLength(), iPoint);
                    }
                }
                NotifyExtraInfo(iPoint - 2);
                ChangeCursorPosition(datetimeScroll.Maximum, 0);
                _iCurrentPoint = iPoint - 2;
            }
            catch (Exception ex)
            {
//                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        public void MoveLeft()
        {
            try
            {
                if (_iCurrentPoint > 0)
                    _iCurrentPoint--;
                NotifyExtraInfo(_iCurrentPoint);
                ChangeCursorPosition(_iCurrentPoint, 0);
            }
            catch (Exception ex)
            {
//                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        public void MoveRight()
        {
            try
            {
                if (_iCurrentPoint < _iTotalPointCount)
                    _iCurrentPoint++;
                NotifyExtraInfo(_iCurrentPoint);
                ChangeCursorPosition(_iCurrentPoint, 0);
            }
            catch (Exception ex)
            {
//                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        private void NotifyExtraInfo(int iPoint)
        {
            RichTextLabel lblChartLabel;
            List<string> lstExtraInfo;
            SeriesFormat seriesFormat;
            TeeChartFormat chartFormat;
            BarData barData;
            BarDataExtra barDataExtra;
            bool isEmpty = false;
            List<string> lstSeries;
            List<object> lstInfo;
            MessageInfo messageInfo;
            string strFormat;
            Dictionary<string, BarDataExtra> dicBarDataExtra;
            List<object> lstMessage;
            LabelMeta labelMeta;
            string strLabelTitle;
            float fClose = 0;
            float f3Close = 0;
            float f6Close = 0;
            float f18Close = 0;
            float f72Close = 0;

            try
            {

                dicBarDataExtra = new Dictionary<string, BarDataExtra>();
                foreach (string strChart in _dicActiveSeries.Keys)
                {
                    lstSeries = _dicActiveSeries[strChart];
                    chartFormat = _dicChartFormat[strChart];

                    foreach (string strSeries in lstSeries)
                    {
                        seriesFormat = chartFormat.GetSeriesFormat(strSeries);
                        barData = chartFormat.DataSource.GetBarData(strSeries);

                        if (iPoint >= barData.GetLength())
                            continue;

                        isEmpty = (barData.DateTime(iPoint) == DateTime.MinValue);

                        if (_lstFieldName.IndexOf("時間") > -1)
                        {
                            tblInfo.Rows[_lstFieldName.IndexOf("時間")].Cells["Value"].Value = isEmpty ? "" : barData.DateTime(iPoint).ToString(DateTimeFormat);
                        }
                        else
                        {
                            tblInfo.Rows.Add(new string[] { "時間", isEmpty ? "" : barData.DateTime(iPoint).ToString(DateTimeFormat) });
                            _lstFieldName.Add("時間");
                        }

                        switch (seriesFormat.DataFieldType)
                        {
                            case DataFieldTypeEnum.BarData:
                                if (_lstFieldName.IndexOf("開盤價") > -1)
                                {
                                    tblInfo.Rows[_lstFieldName.IndexOf("開盤價")].Cells["Value"].Value = isEmpty ? "" : barData.Open(iPoint).ToString("0.00");
                                    UpdateValueColor("開盤價", DataTypeEnum.Open, barData, iPoint);
                                }
                                else
                                {
                                    tblInfo.Rows.Add(new string[] { "開盤價", isEmpty ? "" : barData.Open(iPoint).ToString("0.00") });
                                    _lstFieldName.Add("開盤價");
                                    UpdateValueColor("開盤價", DataTypeEnum.Open, barData, iPoint);
                                }
                                if (_lstFieldName.IndexOf("最高價") > -1)
                                {
                                    tblInfo.Rows[_lstFieldName.IndexOf("最高價")].Cells["Value"].Value = isEmpty ? "" : barData.High(iPoint).ToString("0.00");
                                    UpdateValueColor("最高價", DataTypeEnum.High, barData, iPoint);
                                }
                                else
                                {
                                    tblInfo.Rows.Add(new string[] { "最高價", isEmpty ? "" : barData.High(iPoint).ToString("0.00") });
                                    _lstFieldName.Add("最高價");
                                    UpdateValueColor("最高價", DataTypeEnum.High, barData, iPoint);
                                }
                                if (_lstFieldName.IndexOf("最低價") > -1)
                                {
                                    tblInfo.Rows[_lstFieldName.IndexOf("最低價")].Cells["Value"].Value = isEmpty ? "" : barData.Low(iPoint).ToString("0.00");
                                    UpdateValueColor("最低價", DataTypeEnum.Low, barData, iPoint);
                                }
                                else
                                {
                                    tblInfo.Rows.Add(new string[] { "最低價", isEmpty ? "" : barData.Low(iPoint).ToString("0.00") });
                                    _lstFieldName.Add("最低價");
                                    UpdateValueColor("最低價", DataTypeEnum.Low, barData, iPoint);
                                }
                                if (_lstFieldName.IndexOf("收盤價") > -1)
                                {
                                    tblInfo.Rows[_lstFieldName.IndexOf("收盤價")].Cells["Value"].Value = isEmpty ? "" : barData.Close(iPoint).ToString("0.00");
                                    UpdateValueColor("收盤價", DataTypeEnum.Close, barData, iPoint);
                                    fClose = barData.Close(iPoint);

                                    if (iPoint >= 3)
                                        f3Close = barData.Close(iPoint - 3);
                                    if (iPoint >= 6)
                                        f6Close = barData.Close(iPoint - 6);
                                    if (iPoint >= 18)
                                        f18Close = barData.Close(iPoint - 18);
                                    if (iPoint >= 72)
                                        f72Close = barData.Close(iPoint - 72);

                                }
                                else
                                {
                                    tblInfo.Rows.Add(new string[] { "收盤價", isEmpty ? "" : barData.Close(iPoint).ToString("0.00") });
                                    _lstFieldName.Add("收盤價");
                                    UpdateValueColor("收盤價", DataTypeEnum.Close, barData, iPoint);
                                    fClose = barData.Close(iPoint);
                                }
                                break;
                            case DataFieldTypeEnum.Close:
                                if (_lstFieldName.IndexOf(strSeries) > -1)
                                {
                                    tblInfo.Rows[_lstFieldName.IndexOf(strSeries)].Cells["Value"].Value = isEmpty ? "" : barData.Close(iPoint).ToString("0.00");
                                    UpdateValueColor(strSeries, DataTypeEnum.Close, barData, iPoint);
                                }
                                else
                                {
                                    tblInfo.Rows.Add(new string[] { strSeries, isEmpty ? "" : barData.Close(iPoint).ToString("0.00") });
                                    _lstFieldName.Add(strSeries);
                                    UpdateValueColor(strSeries, DataTypeEnum.Close, barData, iPoint);
                                }

                                break;
                            case DataFieldTypeEnum.Volume:
                                if (_lstFieldName.IndexOf("成交量") > -1)
                                {
                                    tblInfo.Rows[_lstFieldName.IndexOf("成交量")].Cells["Value"].Value = isEmpty ? "" : barData.Volume(iPoint).ToString("0");
                                    UpdateValueColor("成交量", DataTypeEnum.Volume, barData, iPoint);
                                }
                                else
                                {
                                    tblInfo.Rows.Add(new string[] { "成交量", isEmpty ? "" : barData.Volume(iPoint).ToString("0") });
                                    _lstFieldName.Add("成交量");
                                    UpdateValueColor("成交量", DataTypeEnum.Volume, barData, iPoint);
                                }
                                break;
                        }
                    }


                    if (_dicActiveExtraInfo.ContainsKey(strChart))
                    {
                        try
                        {
                            lstExtraInfo = _dicActiveExtraInfo[strChart];
                            _dicChartLabel[strChart].ClearText();
                            _dicChartLabel[strChart].IsUpdateText = true;
                            for (int i = 0; i < lstExtraInfo.Count; i++)
                            {
                                strLabelTitle = "";
                                barDataExtra = _dicExtraInfo[lstExtraInfo[i]];
                                lstInfo = barDataExtra.GetInfo(iPoint);

                                for (int j = 0; j < lstInfo.Count; j++)
                                {
                                    if (_lstFieldName.IndexOf(barDataExtra.GetTitle()[j]) > -1)
                                    {
                                        tblInfo.Rows[_lstFieldName.IndexOf(barDataExtra.GetTitle()[j])].Cells["Value"].Value = isEmpty
                                                                                                                                    ? ""
                                                                                                                                    :   NumericHelper.IsNumeric((string)lstInfo[j])
                                                                                                                                        ?   float.Parse((string)lstInfo[j]).ToString("0.00")
                                                                                                                                        :   (string)lstInfo[j];

                                    }
                                    else
                                    {
                                        tblInfo.Rows.Add(new string[] { barDataExtra.GetTitle()[j], isEmpty 
                                                                                                        ? "" 
                                                                                                        : NumericHelper.IsNumeric((string)lstInfo[j])
                                                                                                            ?   float.Parse((string)lstInfo[j]).ToString("0.00") 
                                                                                                            :   (string)lstInfo[j]});
                                        _lstFieldName.Add(barDataExtra.GetTitle()[j]);

                                    }

                                    strFormat = ((barDataExtra.GetTitle()[j] == "成交量") ||
                                                 (barDataExtra.GetTitle()[j] == "3V") ||
                                                 (barDataExtra.GetTitle()[j] == "6V") ||
                                                 (barDataExtra.GetTitle()[j] == "18V"))
                                                    ? "0"
                                                    : "0.00";


                                    labelMeta = new LabelMeta();
                                    labelMeta.ForeColor = Color.Black;
                                    labelMeta.Font = Font;
                                    labelMeta.Text = barDataExtra.GetTitle()[j] + ":" + (isEmpty
                                                                                            ? ""
                                                                                            :  NumericHelper.IsNumeric((string)lstInfo[j])
                                                                                                ?   float.Parse((string)lstInfo[j]).ToString(strFormat)
                                                                                                :   (string)lstInfo[j]);

                                    if (!isEmpty && ((barDataExtra.GetTitle()[j] == "A值") || (barDataExtra.GetTitle()[j] == "B值") || (barDataExtra.GetTitle()[j] == "C值")))
                                    {
                                        labelMeta.Text += (float.Parse((string)lstInfo[j]) > fClose) ? "↑" : "↓";
                                        labelMeta.ForeColor = (float.Parse((string)lstInfo[j]) > fClose) ? Color.Red : Color.Green;
                                    }

                                    if (!isEmpty && (barDataExtra.GetTitle()[j] == "3MA"))
                                    {
                                        labelMeta.Text += (f3Close < fClose) ? "↑" : "↓";
                                        labelMeta.ForeColor = (f3Close < fClose ? Color.Red : Color.Green);
                                    }

                                    if (!isEmpty && (barDataExtra.GetTitle()[j] == "6MA"))
                                    {
                                        labelMeta.Text += (f6Close < fClose) ? "↑" : "↓";
                                        labelMeta.ForeColor = (f6Close < fClose ? Color.Red : Color.Green);
                                    }

                                    if (!isEmpty && (barDataExtra.GetTitle()[j] == "18MA"))
                                    {
                                        labelMeta.Text += (f18Close < fClose) ? "↑" : "↓";
                                        labelMeta.ForeColor = (f18Close < fClose ? Color.Red : Color.Green);
                                    }

                                    if (!isEmpty && (barDataExtra.GetTitle()[j] == "72MA"))
                                    {
                                        labelMeta.Text += (f72Close < fClose) ? "↑" : "↓";
                                        labelMeta.ForeColor = (f72Close < fClose ? Color.Red : Color.Green);
                                    }

                                    if (!isEmpty && (barDataExtra.GetTitle()[j] == "紅值"))
                                    {
                                        labelMeta.Text += (float.Parse(lstInfo[j].ToString()) > 0) ? "↑" : "↓";
                                        labelMeta.ForeColor = (float.Parse(lstInfo[j].ToString()) > 0 ? Color.Red : Color.Green);
                                    }

                                    if (!isEmpty && (barDataExtra.GetTitle()[j] == "黑值"))
                                    {
                                        labelMeta.Text += (float.Parse(lstInfo[j].ToString()) > 0) ? "↑" : "↓";
                                        labelMeta.ForeColor = (float.Parse(lstInfo[j].ToString()) > 0 ? Color.Red : Color.Green);
                                    }

                                    if (!isEmpty && (barDataExtra.GetTitle()[j] == "三日紅黑值"))
                                    {
                                        labelMeta.Text += (float.Parse(lstInfo[j].ToString()) > 0) ? "↑" : "↓";
                                        labelMeta.ForeColor = (float.Parse(lstInfo[j].ToString()) > 0 ? Color.Red : Color.Green);
                                    }

                                    if (!isEmpty && (barDataExtra.GetTitle()[j] == "漲跌"))
                                    {
                                        labelMeta.Text += float.Parse(lstInfo[j].ToString()) > 0 ? "↑" : "↓";
                                        labelMeta.ForeColor = (float.Parse(lstInfo[j].ToString()) > 0 ? Color.Red : Color.Green);
                                    }

                                    if (!isEmpty && (barDataExtra.GetTitle()[j] == "漲跌%"))
                                    {
                                        labelMeta.Text += float.Parse(lstInfo[j].ToString()) > 0 ? "↑" : "↓";
                                        labelMeta.ForeColor = (float.Parse(lstInfo[j].ToString()) > 0 ? Color.Red : Color.Green);
                                    }

                                    _dicChartLabel[strChart].AddText(labelMeta);

                                    strFormat = ((barDataExtra.GetTitle()[j] == "成交量") ||
                                                 (barDataExtra.GetTitle()[j] == "3V") ||
                                                 (barDataExtra.GetTitle()[j] == "6V") ||
                                                 (barDataExtra.GetTitle()[j] == "18V"))
                                                    ? "0"
                                                    : "0.00";

                                    strLabelTitle += "    " + barDataExtra.GetTitle()[j] + ":" + (isEmpty
                                                                                                    ? ""
                                                                                                    : NumericHelper.IsNumeric((string)lstInfo[j]) 
                                                                                                        ? float.Parse((string)lstInfo[j]).ToString(strFormat)
                                                                                                        : (string)lstInfo[j]);

                                    if (!isEmpty && ((barDataExtra.GetTitle()[j] == "A值") || (barDataExtra.GetTitle()[j] == "B值") || (barDataExtra.GetTitle()[j] == "C值")))
                                        strLabelTitle += (float.Parse((string)lstInfo[j]) > fClose) ? "↑" : "↓";

                                    if (!isEmpty && (barDataExtra.GetTitle()[j] == "3MA"))
                                        strLabelTitle += (f3Close < fClose) ? "↑" : "↓";

                                    if (!isEmpty && (barDataExtra.GetTitle()[j] == "6MA"))
                                        strLabelTitle += (f6Close < fClose) ? "↑" : "↓";

                                    if (!isEmpty && (barDataExtra.GetTitle()[j] == "18MA"))
                                        strLabelTitle += (f18Close < fClose) ? "↑" : "↓";

                                    if (!isEmpty && (barDataExtra.GetTitle()[j] == "72MA"))
                                        strLabelTitle += (f72Close < fClose) ? "↑" : "↓";

                                    if (!isEmpty && (barDataExtra.GetTitle()[j] == "紅值"))
                                        strLabelTitle += float.Parse(lstInfo[j].ToString()) > 0 ? "↑" : "↓";

                                    if (!isEmpty && (barDataExtra.GetTitle()[j] == "黑值"))
                                        strLabelTitle += float.Parse(lstInfo[j].ToString()) > 0 ? "↑" : "↓";

                                    if (!isEmpty && (barDataExtra.GetTitle()[j] == "三日紅黑值"))
                                        strLabelTitle += float.Parse(lstInfo[j].ToString()) > 0 ? "↑" : "↓";

                                    if (!isEmpty && (barDataExtra.GetTitle()[j] == "漲跌"))
                                        strLabelTitle += float.Parse(lstInfo[j].ToString()) > 0 ? "↑" : "↓";

                                    if (!isEmpty && (barDataExtra.GetTitle()[j] == "漲跌%"))
                                        strLabelTitle += float.Parse(lstInfo[j].ToString()) > 0 ? "↑" : "↓";

                                    strLabelTitle += "  ";
                                }
                                //_dicChartLabel[strChart].Text = strLabelTitle;
                                
//                                _dicChartLabel[strChart].IsUpdateText = true;
                            }
                        }
                        catch (Exception ex)
                        {
//                            MessageBox.Show(ex.Message + "," + ex.StackTrace);
                        }
                    }
                    //                    _dicChartLabel[strChart].Text = strLabelTitle;
//                    _dicChartLabel[strChart].IsUpdateText = true;

                    //_dicChartLabel[strChart].Update();
                    _dicChartLabel[strChart].Refresh();
                    if(_dicChartLabelAlignment.ContainsKey(strChart))
                    {
                        switch(_dicChartLabelAlignment[strChart])
                        {
                            case LabelAlignmentEnum.Left:
                                _dicChartLabel[strChart].Left = 0;
                                break;
                            case LabelAlignmentEnum.Center:
                                _dicChartLabel[strChart].Left = (int)(_dicChart[strChart].Width - _dicChartLabel[strChart].Width) / 2;
                                break;
                            case LabelAlignmentEnum.Right:
                                _dicChartLabel[strChart].Left = (int)(_dicChart[strChart].Width - _dicChartLabel[strChart].Width);
                                break;

                        }
                    }
//                    _dicChartLabel[strChart].Visible = false;
//                    _dicChartLabel[strChart].Visible = true;
                }

                lstMessage = new List<object>();
                lstMessage.Add(iPoint);
                lstMessage.Add(_dicExtraInfo);
                messageInfo = new MessageInfo();
                messageInfo.MessageTicks = DateTime.Now.Ticks;
                messageInfo.MessageSubject = "CursorPositionChanged";
                messageInfo.Message = lstMessage;
                MessageSubject.Instance().Subject.Notify(messageInfo);
            }
            catch (Exception ex)
            {
//                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        public void StartHook()
        {
            try
            {
                _keyboardHook = new KeyboardHook();
                _keyboardHook.OnKeyboardHook += new KeyboardHookEventHandler(OnChartKeyPress);
                _keyboardHook.StartHook();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        public void StopHook()
        {
            try
            {
                if (_keyboardHook != null)
                    _keyboardHook.StopHook();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        public SignalInfoPane SignalInfoPane
        {
            get { return signalInfoPane; }
        }

        public bool IsShowLightPane
        {
            get { return _isShowLightPane; }
            set 
            { 
                _isShowLightPane = value;
                RelocationComponent();
                RepositionComponent();
            }
        }

        public bool IsShowInfoTable
        {
            get { return _isShowInfoTable; }
            set 
            { 
                _isShowInfoTable = value;
                RepositionComponent();
            }
        }

        public bool IsShowScale
        {
            get { return _isShowScale; }
            set 
            { 
                _isShowScale = value;
                RepositionComponent();
            }
        }

        public bool ShowHorizontalCursor
        {
            get { return _isShowHorizontalCursor; }
            set { _isShowHorizontalCursor = value; }
        }

        public bool ShowVerticalCursor
        {
            get { return _isShowVerticalCursor; }
            set { _isShowVerticalCursor = value; }
        }

        public string DateTimeFormat
        {
            get { return _strDateTimeFormat; }
            set { _strDateTimeFormat = value; }
        }

        public int PointPerPage
        {
            get { return _iPointPerPage; }
            set
            {
                bool NeedRefresh = (_iPointPerPage != value);
                _iPointPerPage = value;
                if (NeedRefresh)
                    RefreshXScale();
            }

/*
            get { return _iDefaultPointPerPage; }
            set 
            {
                bool NeedRefresh = (_iDefaultPointPerPage != value);
                _iDefaultPointPerPage = value;
                if(NeedRefresh)
                    RefreshXScale();
            }
 */ 
        }

        public IDataSource GetDataSource(string strChartName)
        {
            return (_dicChart.ContainsKey(strChartName) == false)
                    ?   null
                    :   _dicChartFormat[strChartName].DataSource;
        }

        public void AddExtraInfo(string strName, List<string> lstField)
        {
            AddExtraInfo(strName, lstField, lstField);
        }

        public void AddExtraInfo(string strName, List<string> lstField, List<string>lstTitle)
        {
            BarDataExtra barDataExtra;
            barDataExtra = new BarDataExtra();
            barDataExtra.SetField(lstField, lstTitle);

            if (_dicExtraInfo.ContainsKey(strName))
            {                
                _dicExtraInfo[strName] = barDataExtra;                
            }
            else
            {
                _dicExtraInfo.Add(strName, barDataExtra);
            }
        }

        public void AddActiveExtraInfo(string strChartName, string strExtraInfo)
        {
            List<string> lstExtraInfo;

            if (_dicActiveExtraInfo.ContainsKey(strChartName) == false)
                _dicActiveExtraInfo.Add(strChartName, new List<string>());


            lstExtraInfo = _dicActiveExtraInfo[strChartName];
            if(lstExtraInfo.IndexOf(strExtraInfo) < 0)
                lstExtraInfo.Add(strExtraInfo);
        }

        public void AddControlLine(string strChartName, DirectionEnum eDirection, float fValue, Color cColor)
        {
            try
            {
                CursorTool cursorTool;

                if(_dicChart.ContainsKey(strChartName) == false)
                    return;
                
                cursorTool = new CursorTool();
                cursorTool.FollowMouse = false;                
                
                switch (eDirection)
                {
                    case DirectionEnum.Horizontal:
                        cursorTool.Style = CursorToolStyles.Horizontal;                        
                        break;  
                    case DirectionEnum.Vertical:
                        cursorTool.Style = CursorToolStyles.Vertical;                        
                        break;
                }
                
                cursorTool.Pen = new Steema.TeeChart.Drawing.ChartPen(cColor);
                _dicChart[strChartName].Tools.Add(cursorTool);

                if (_dicControlLine.ContainsKey(strChartName) == false)
                    _dicControlLine.Add(strChartName, new List<CursorTool>());
                _dicControlLine[strChartName].Add(cursorTool);

                if (_dicControlLineValue.ContainsKey(strChartName) == false)
                    _dicControlLineValue.Add(strChartName, new List<float>());
                _dicControlLineValue[strChartName].Add(fValue);
            }
            catch (Exception ex)
            {
//                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        public void AddSeriesField(string strSeriesName, List<string> lstFieldName)
        {
            if (_dicFieldName.ContainsKey(strSeriesName))
                return;

            _dicFieldName.Add(strSeriesName, lstFieldName);
        }

        public void ProcessExtraInfo(IResultSet resultSet)
        {
            BarDataExtra barDataExtra = null;
            List<object> lstData;
            
            try
            {
                foreach(string strKey in _dicExtraInfo.Keys)
                {
                    
                    barDataExtra = _dicExtraInfo[strKey];
                    barDataExtra.ClearData();
                    resultSet.Reset();

                    while (resultSet.Read())
                    {
                        lstData = new List<object>();
                        for (int i = 0; i < barDataExtra.GetFieldName().Count; i++)
                            lstData.Add((string)resultSet.Cells(barDataExtra.GetFieldName()[i]));
                        barDataExtra.AddData(lstData);
                    }
                    if(signalInfoPane.DisplayKey == strKey)
                        signalInfoPane.BarDataExtra = barDataExtra;
                }
                
                
            }
            catch (Exception ex)
            {
//                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        public void ProcessResultSet(string strChartName, string strSeriesName, IResultSet resultSet)
        {
            string[] strValues = null;
            List<string> lstFieldName = null;            
            BarData barData;
            

            if (_dicChartFormat.ContainsKey(strChartName) == false)
            {
                MessageBox.Show("The chart name (" + strChartName + ") doesn't exist!");
                return;
            }

            try
            {
                if (_dicFieldName.ContainsKey(strSeriesName) == false)
                    return;

                lstFieldName = _dicFieldName[strSeriesName];
                barData = new BarData();

                if (lstFieldName.Count == 2)
                {
                    resultSet.Reset();                    
                    while (resultSet.Read())
                    {
                        strValues = new string[2];
                        for (int i = 0; i < strValues.Length; i++)
                        {
                            strValues[i] = (string)resultSet.Cells(lstFieldName[i]);
                            if (strValues[i] == "")
                                strValues[i] = EMPTY_DATA;
                        }
                        barData.AddData((strValues[0].Trim().Length == 0) || (strValues[0] == "NaN") ? DateTime.MinValue : DateTime.Parse(strValues[0]),
                                        strValues[1] == EMPTY_DATA ? float.NaN : float.Parse(strValues[1]),
                                        strValues[1] == EMPTY_DATA ? float.NaN : float.Parse(strValues[1]),
                                        strValues[1] == EMPTY_DATA ? float.NaN : float.Parse(strValues[1]),
                                        strValues[1] == EMPTY_DATA ? float.NaN : float.Parse(strValues[1]),
                                        0);                        
                    }                    
                }
                else
                {
                    resultSet.Reset();

                    while (resultSet.Read())
                    {
                        strValues = new string[5];
                        for (int i = 0; i < strValues.Length; i++)
                        {
                            strValues[i] = (string)resultSet.Cells(lstFieldName[i]);
                            if (strValues[i] == "")
                                strValues[i] = EMPTY_DATA;
                        }
                        barData.AddData((strValues[0].Trim().Length == 0) || (strValues[0] == "NaN") ? DateTime.MinValue : DateTime.Parse(strValues[0]),
                                        strValues[1] == EMPTY_DATA ? float.NaN : float.Parse(strValues[1]),
                                        strValues[2] == EMPTY_DATA ? float.NaN : float.Parse(strValues[2]),
                                        strValues[3] == EMPTY_DATA ? float.NaN : float.Parse(strValues[3]),
                                        strValues[4] == EMPTY_DATA ? float.NaN : float.Parse(strValues[4]),
                                        0);
                    }
                }

                if (strSeriesName == BaseSeriesName)
                    _baseSeriesData = barData;

                _dicChartFormat[strChartName].DataSource.AddBarData(strSeriesName, barData);

/*
                //Process BarDataExtra
                if (_dicActiveExtraInfo.ContainsKey(strChartName))
                {
                    lstExtraInfo = _dicActiveExtraInfo[strChartName];

                    for (int iExtra = 0; iExtra < lstExtraInfo.Count; iExtra++)
                    {
                        barDataExtra = _dicExtraInfo[lstExtraInfo[iExtra]];
                        resultSet.Reset();

                        while (resultSet.Read())
                        {
                            lstData = new List<object>();
                            for (int i = 0; i < barDataExtra.GetFieldName().Count; i++)
                                lstData.Add((string)resultSet.Cells(barDataExtra.GetFieldName()[i]));
                            barDataExtra.AddData(lstData);
                        }
                    }
                }
*/
                datetimeScroll.Minimum = 0;
                datetimeScroll.Maximum = resultSet.RowCount - _iPointPerPage;
                _iTotalPointCount = resultSet.RowCount;
                _iPointPerPage = Math.Min(_iTotalPointCount, _iDefaultPointPerPage);

                foreach (TeeChartFormat teeChartFormat in _dicChartFormat.Values)
                    teeChartFormat.BaseSeriesData = _baseSeriesData;
            }
            catch (Exception ex)
            {
//                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }        

        public void AddActiveSeries(string strChartName, string strSeriesName)
        {
            try
            {
                if (_dicActiveSeries.ContainsKey(strChartName) == false)
                    return;

                if (_dicActiveSeries[strChartName].IndexOf(strSeriesName) > -1)
                    return;

                _dicActiveSeries[strChartName].Add(strSeriesName);
            }
            catch (Exception ex)
            {
//                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        public void RemoveActiveSeries(string strChartName, string strSeriesName)
        {
            try
            {
            }
            catch (Exception ex)
            {
//                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        public void AdddSeries(string strChartName, string strSeriesName, ScaleTypeEnum eScale, DataFieldTypeEnum eDataField, ChartStyleEnum eChartStyle)
        {
            SeriesFormat seriesFormat;
            try
            {
                if (_dicSeries[strChartName].IndexOf(strSeriesName) > -1)
                    return;

                seriesFormat = new SeriesFormat();                
                seriesFormat.ScaleType = eScale;
                seriesFormat.DataFieldType = eDataField;
                seriesFormat.SeriesStyle = eChartStyle;                
                
                _dicChartFormat[strChartName].AddSeries(strSeriesName, seriesFormat);
                _dicSeries[strChartName].Add(strSeriesName);                    
            }
            catch (Exception ex)
            {
//                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        public void SetChartSize(string strChartName, float fSize)
        {
            try
            {
                if (_dicChartSize.ContainsKey(strChartName) == false)
                    return;
                
                _dicChartSize[strChartName] = fSize;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        private void FormatLabel(RichTextLabel lblChartLabel)
        {
            try
            {
                lblChartLabel.AutoSize = true;
                lblChartLabel.BackColor = Color.Transparent;
                lblChartLabel.ForeColor = Color.Black;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        private void RepositionComponent()
        {
            try
            {
                if (IsShowInfoTable == false)
                {
                    tblInfo.Width = 0;
                    splContainer.SplitterDistance = splContainer.Width;
                }
                else
                {
                    tblInfo.Width = 280;
                    splContainer.SplitterDistance = splContainer.Width - tblInfo.Width;
                }
                tblInfo.Visible = IsShowInfoTable;
                btnZoomIn.Visible = IsShowScale;
                btnZoomOut.Visible = IsShowScale;
            }
            catch (Exception ex)
            {
//                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        public void SetLabelAlignment(string strChartName, LabelAlignmentEnum enumAlignment)
        {
            try
            {
                if(_dicChartLabelAlignment.ContainsKey(strChartName))
                    _dicChartLabelAlignment[strChartName] = enumAlignment;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        public void AddChart(string strChartName)
        {
            if (_dicChart.ContainsKey(strChartName))
                return;

            RepositionComponent();
            TeeChartFormat chartFormat;
            RichTextLabel lblChartLabel;
            RichTextLabel lblOriginal = null;
            TChart chtChart;
            TChart chtOriginal = null;
            CursorTool cursorTool;
            SplitContainer splTemp;
            SplitContainer splChartContainer;
            int iSplitDistance;

            _lstChartName.Add(strChartName);

            iSplitDistance = (int)((double)(splContainer.Height - DEFAULT_BOTTOM_HEIGHT)/ (double)_lstChartName.Count);

            chtChart = new TChart();
            lblChartLabel = new RichTextLabel();
            lblChartLabel.Font = Font;
            //FormatLabel(lblChartLabel);
            //chtChart.Page.MaxPointsPerPage = _iPointPerPage;            
            chartFormat = new TeeChartFormat(chtChart);
            chartFormat.DateTimeFormat = DateTimeFormat;
            chartFormat.DataSource = new DefaultDataSource();
            chartFormat.SetChartTitle("");
            chartFormat.BaseSeriesData = _baseSeriesData;
            _dicChart.Add(strChartName, chtChart);
            _dicChartSize.Add(strChartName, (float)1.0);
            _dicChartFormat.Add(strChartName, chartFormat);
            _dicSeries.Add(strChartName, new List<string>());
            _dicActiveSeries.Add(strChartName, new List<string>());
            _dicChartLabel.Add(strChartName, lblChartLabel);
            _dicChartLabelAlignment.Add(strChartName, LabelAlignmentEnum.Left);
            //_dicChartLabelAlignment.Add(strChartName, LabelAlignmentEnum.Right);

            switch (_lstChartName.Count)
            {
                case 1:                    
                    splContainer.Panel1.Controls.Add(chtChart);
                    splContainer.Panel1.Controls.Add(lblChartLabel);
                    chtChart.Dock = DockStyle.Fill;
/*
                    chtChart.Dock = DockStyle.None;
                    chtChart.Top = lblChartLabel.Height;
                    chtChart.Left = 0;
                    chtChart.Height = splContainer.Panel1.Height - lblChartLabel.Height;
                    chtChart.Width = splContainer.Panel1.Width;
 */ 
                    lblChartLabel.Dock = DockStyle.None;
                    lblChartLabel.Left = 0;
                    lblChartLabel.Top = 0;
                    lblChartLabel.BringToFront();
                    break;
                case 2:
                    if(splContainer.Panel1.Controls[0] is TChart)
                        chtOriginal = (TChart)splContainer.Panel1.Controls[0];
                    if (splContainer.Panel1.Controls[0] is RichTextLabel)
                        lblOriginal = (RichTextLabel)splContainer.Panel1.Controls[0];

                    if (splContainer.Panel1.Controls[1] is TChart)
                        chtOriginal = (TChart)splContainer.Panel1.Controls[1];
                    if (splContainer.Panel1.Controls[1] is RichTextLabel)
                        lblOriginal = (RichTextLabel)splContainer.Panel1.Controls[1];

                    splContainer.Panel1.Controls.RemoveAt(0);
                    splContainer.Panel1.Controls.RemoveAt(0);
                    splChartContainer = new SplitContainer();                    
                    splChartContainer.Orientation = Orientation.Horizontal;
                    splChartContainer.Panel1.Controls.Add(chtOriginal);
                    splChartContainer.Panel1.Controls.Add(lblOriginal);
                    splChartContainer.Panel2.Controls.Add(chtChart);
                    splChartContainer.Panel2.Controls.Add(lblChartLabel);
                    splChartContainer.SplitterDistance = iSplitDistance;
                    splContainer.Panel1.Controls.Add(splChartContainer);
                    splChartContainer.Dock = DockStyle.Fill;
                    chtOriginal.Dock = DockStyle.Fill;
/*
                    chtOriginal.Dock = DockStyle.None;
                    chtOriginal.Top = lblOriginal.Height;
                    chtOriginal.Left = 0;
                    chtOriginal.Width = splChartContainer.Panel1.Width;
                    chtOriginal.Height = splChartContainer.Panel1.Height - lblOriginal.Height;
*/
                    lblOriginal.Dock = DockStyle.None;
                    lblOriginal.Left = 0;
                    lblOriginal.Top = 0;
                    lblOriginal.BringToFront();
                    chtChart.Dock = DockStyle.Fill;
/*
                    chtChart.Dock = DockStyle.None;
                    chtChart.Top = lblChartLabel.Height;
                    chtChart.Left = 0;
                    chtChart.Height = splContainer.Panel2.Height - lblChartLabel.Height;
                    chtChart.Width = splContainer.Panel2.Width;
*/
                    lblChartLabel.Dock = DockStyle.None;
                    lblChartLabel.Left = 0;
                    lblChartLabel.Top = 0;
                    lblChartLabel.BringToFront();
                    break;
                default:
                    splTemp = (SplitContainer)splContainer.Panel1.Controls[0];
                    for (int i = 0; i < _lstChartName.Count - 3; i++)
                    {
                        splTemp = (SplitContainer)splTemp.Panel2.Controls[0];
                        splTemp.SplitterDistance = iSplitDistance;
                    }

                    if (splTemp.Panel2.Controls[0] is TChart)
                        chtOriginal = (TChart)splTemp.Panel2.Controls[0];
                    if (splTemp.Panel2.Controls[0] is RichTextLabel)
                        lblOriginal = (RichTextLabel)splTemp.Panel2.Controls[0];

                    if (splTemp.Panel2.Controls[1] is TChart)
                        chtOriginal = (TChart)splTemp.Panel2.Controls[1];
                    if (splTemp.Panel2.Controls[1] is RichTextLabel)
                        lblOriginal = (RichTextLabel)splTemp.Panel2.Controls[1];
                    
                    splTemp.Panel2.Controls.RemoveAt(0);
                    splTemp.Panel2.Controls.RemoveAt(0);
                    splChartContainer = new SplitContainer();                    
                    splChartContainer.Orientation = Orientation.Horizontal;
                    splChartContainer.Panel1.Controls.Add(chtOriginal);
                    splChartContainer.Panel1.Controls.Add(lblOriginal);
                    splChartContainer.Panel2.Controls.Add(chtChart);
                    splChartContainer.Panel2.Controls.Add(lblChartLabel);
                    splChartContainer.SplitterDistance = iSplitDistance;
                    splTemp.Panel2.Controls.Add(splChartContainer);
                    splTemp.SplitterDistance = iSplitDistance;
                    splChartContainer.Dock = DockStyle.Fill;
                    chtOriginal.Dock = DockStyle.Fill;
/*
                    chtOriginal.Dock = DockStyle.None;
                    chtOriginal.Top = lblOriginal.Height;
                    chtOriginal.Left = 0;
                    chtOriginal.Width = splChartContainer.Panel1.Width;
                    chtOriginal.Height = splChartContainer.Panel1.Height - lblOriginal.Height;
*/
                    lblOriginal.Dock = DockStyle.None;
                    lblOriginal.Left = 0;
                    lblOriginal.Top = 0;
                    lblOriginal.BringToFront();

                    chtChart.Dock = DockStyle.Fill;
/*
                    chtChart.Dock = DockStyle.None;
                    chtChart.Top = lblChartLabel.Height;
                    chtChart.Left = 0;
                    chtChart.Height = splContainer.Panel2.Height - lblChartLabel.Height;
                    chtChart.Width = splContainer.Panel2.Width;
*/
                    lblChartLabel.Dock = DockStyle.None;
                    lblChartLabel.Left = 0;
                    lblChartLabel.Top = 0;
                    lblChartLabel.BringToFront();
                    break;
            }
               
            for (int i = 0; i < _lstChartName.Count - 1; i++)
            {
                _dicChartFormat[_lstChartName[i]].SetAxisVisible(AAA.Meta.Chart.PositionEnum.Bottom, false);
                _dicChartFormat[_lstChartName[i]].SetMargin(PositionEnum.Bottom, 5);
            }

            if (ShowHorizontalCursor)
            {
                cursorTool = new Steema.TeeChart.Tools.CursorTool();
                cursorTool.FollowMouse = true;
                cursorTool.Style = Steema.TeeChart.Tools.CursorToolStyles.Horizontal;
                cursorTool.Change += new Steema.TeeChart.Tools.CursorChangeEventHandler(CursorTool_Change);
                chtChart.Tools.Add(cursorTool);
                _dicHorizontalCursor.Add(strChartName, cursorTool);
            }

            if (ShowVerticalCursor)
            {                
                cursorTool = new Steema.TeeChart.Tools.CursorTool();
                cursorTool.FollowMouse = true;
                cursorTool.Style = Steema.TeeChart.Tools.CursorToolStyles.Vertical;
                cursorTool.Change += new Steema.TeeChart.Tools.CursorChangeEventHandler(CursorTool_Change);
                chtChart.Tools.Add(cursorTool);
                _dicVerticalCursor.Add(strChartName, cursorTool);
            }
 
        }

        public void SetYAxisFormat(string strChartName, string strFormat)
        {
            try
            {
                _dicChartFormat[strChartName].YAxisFormat = strFormat;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        private void OnChartKeyPress(AAA.Base.Util.Hook.KeyEventArgs e)
        {
            try
            {
//                MessageBox.Show("KeyChar : " + e.KeyChar);
            }
            catch (Exception ex)
            {
//                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }            
        }

        private void UpdateValueColor(string strField, DataTypeEnum eDataType, BarData barData, int iPoint)
        {
            try
            {
                Color cColor = Color.Black;

                if(iPoint <= 1)                                    
                    return;

                switch(eDataType)
                {
                    case DataTypeEnum.Open:
                        cColor = barData.Open(iPoint) > barData.Open(iPoint - 1)
                                    ? Color.Red
                                    : barData.Open(iPoint) < barData.Open(iPoint - 1)
                                        ? Color.Green
                                        : Color.Black;
                        break;
                    case DataTypeEnum.High:
                        cColor = barData.High(iPoint) > barData.High(iPoint - 1)
                                    ? Color.Red
                                    : barData.High(iPoint) < barData.High(iPoint - 1)
                                        ? Color.Green
                                        : Color.Black;
                        break;
                    case DataTypeEnum.Low:
                        cColor = barData.Low(iPoint) > barData.Low(iPoint - 1)
                                    ? Color.Red
                                    : barData.Low(iPoint) < barData.Low(iPoint - 1)
                                        ? Color.Green
                                        : Color.Black;
                        break;
                    case DataTypeEnum.Close:
                        cColor = barData.Close(iPoint) > barData.Close(iPoint - 1)
                                    ? Color.Red
                                    : barData.Close(iPoint) < barData.Close(iPoint - 1)
                                        ? Color.Green
                                        : Color.Black;
                        break;
                    case DataTypeEnum.Volume:
                        cColor = barData.Volume(iPoint) > barData.Volume(iPoint - 1)
                                    ? Color.Red
                                    : barData.Volume(iPoint) < barData.Volume(iPoint - 1)
                                        ? Color.Green
                                        : Color.Black;
                        break;
                }

                tblInfo.Rows[_lstFieldName.IndexOf(strField)].Cells["Value"].Style.ForeColor = cColor;
            }
            catch (Exception ex)
            {
//                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        private void UpdateCursorPosition(int iPoint, double dYValue)
        {
            try
            {
                _isChangeCursorPosition = false;

                RichTextLabel lblChartLabel;
                List<string> lstExtraInfo;
                SeriesFormat seriesFormat;
                TeeChartFormat chartFormat;
                BarData barData;
                BarDataExtra barDataExtra;
                bool isEmpty = false;
                List<string> lstSeries;
                List<object> lstInfo;
                MessageInfo messageInfo;
                Dictionary<string, BarDataExtra> dicBarDataExtra;
                List<object> lstMessage;
                LabelMeta labelMeta;
                string strLabelTitle;
                float fClose = 0;
                float f3Close = 0;
                float f6Close = 0;
                float f18Close = 0;
                float f72Close = 0;


                foreach (CursorTool cursorTool in _dicVerticalCursor.Values)
                    cursorTool.XValue = iPoint;

                if (double.IsNaN(dYValue) == false)
                    foreach (CursorTool cursorTool in _dicHorizontalCursor.Values)
                        cursorTool.YValue = dYValue;

                NotifyExtraInfo(iPoint);

/*
                dicBarDataExtra = new Dictionary<string, BarDataExtra>();

                foreach (string strChart in _dicActiveSeries.Keys)
                {
                    lstSeries = _dicActiveSeries[strChart];
                    chartFormat = _dicChartFormat[strChart];

                    foreach (string strSeries in lstSeries)
                    {
                        seriesFormat = chartFormat.GetSeriesFormat(strSeries);
                        barData = chartFormat.DataSource.GetBarData(strSeries);

                        if (iPoint >= barData.GetLength())
                            continue;

                        isEmpty = (barData.DateTime(iPoint) == DateTime.MinValue);

                        if (_lstFieldName.IndexOf("時間") > -1)
                        {
                            tblInfo.Rows[_lstFieldName.IndexOf("時間")].Cells["Value"].Value = isEmpty ? "" : barData.DateTime(iPoint).ToString(DateTimeFormat);
                        }
                        else
                        {
                            tblInfo.Rows.Add(new string[] { "時間", isEmpty ? "" : barData.DateTime(iPoint).ToString(DateTimeFormat) });
                            _lstFieldName.Add("時間");
                        }

                        switch (seriesFormat.DataFieldType)
                        {
                            case DataFieldTypeEnum.BarData:
                                if (_lstFieldName.IndexOf("開盤價") > -1)
                                {
                                    tblInfo.Rows[_lstFieldName.IndexOf("開盤價")].Cells["Value"].Value = isEmpty ? "" : barData.Open(iPoint).ToString("0.00");
                                    UpdateValueColor("開盤價", DataTypeEnum.Open, barData, iPoint);
                                }
                                else
                                {
                                    tblInfo.Rows.Add(new string[] { "開盤價", isEmpty ? "" : barData.Open(iPoint).ToString("0.00") });
                                    _lstFieldName.Add("開盤價");
                                    UpdateValueColor("開盤價", DataTypeEnum.Open, barData, iPoint);
                                }
                                if (_lstFieldName.IndexOf("最高價") > -1)
                                {
                                    tblInfo.Rows[_lstFieldName.IndexOf("最高價")].Cells["Value"].Value = isEmpty ? "" : barData.High(iPoint).ToString("0.00");
                                    UpdateValueColor("最高價", DataTypeEnum.High, barData, iPoint);
                                }
                                else
                                {
                                    tblInfo.Rows.Add(new string[] { "最高價", isEmpty ? "" : barData.High(iPoint).ToString("0.00") });
                                    _lstFieldName.Add("最高價");
                                    UpdateValueColor("最高價", DataTypeEnum.High, barData, iPoint);
                                }
                                if (_lstFieldName.IndexOf("最低價") > -1)
                                {
                                    tblInfo.Rows[_lstFieldName.IndexOf("最低價")].Cells["Value"].Value = isEmpty ? "" : barData.Low(iPoint).ToString("0.00");
                                    UpdateValueColor("最低價", DataTypeEnum.Low, barData, iPoint);
                                }
                                else
                                {
                                    tblInfo.Rows.Add(new string[] { "最低價", isEmpty ? "" : barData.Low(iPoint).ToString("0.00") });
                                    _lstFieldName.Add("最低價");
                                    UpdateValueColor("最低價", DataTypeEnum.Low, barData, iPoint);                                    
                                }
                                if (_lstFieldName.IndexOf("收盤價") > -1)
                                {
                                    tblInfo.Rows[_lstFieldName.IndexOf("收盤價")].Cells["Value"].Value = isEmpty ? "" : barData.Close(iPoint).ToString("0.00");
                                    UpdateValueColor("收盤價", DataTypeEnum.Close, barData, iPoint);
                                    fClose = barData.Close(iPoint);

                                    if(iPoint >= 3)
                                        f3Close = barData.Close(iPoint - 3);
                                    if (iPoint >= 6)
                                        f6Close = barData.Close(iPoint - 6);
                                    if (iPoint >= 18)
                                        f18Close = barData.Close(iPoint - 18);
                                    if (iPoint >= 72)
                                        f72Close = barData.Close(iPoint - 72);

                                }
                                else
                                {
                                    tblInfo.Rows.Add(new string[] { "收盤價", isEmpty ? "" : barData.Close(iPoint).ToString("0.00") });
                                    _lstFieldName.Add("收盤價");
                                    UpdateValueColor("收盤價", DataTypeEnum.Close, barData, iPoint);
                                    fClose = barData.Close(iPoint);
                                }
                                break;
                            case DataFieldTypeEnum.Close:
                                if (_lstFieldName.IndexOf(strSeries) > -1)
                                {
                                    tblInfo.Rows[_lstFieldName.IndexOf(strSeries)].Cells["Value"].Value = isEmpty ? "" : barData.Close(iPoint).ToString("0.00");
                                    UpdateValueColor(strSeries, DataTypeEnum.Close, barData, iPoint);
                                }
                                else
                                {
                                    tblInfo.Rows.Add(new string[] { strSeries, isEmpty ? "" : barData.Close(iPoint).ToString("0.00") });
                                    _lstFieldName.Add(strSeries);
                                    UpdateValueColor(strSeries, DataTypeEnum.Close, barData, iPoint);
                                }

                                break;
                            case DataFieldTypeEnum.Volume:
                                if (_lstFieldName.IndexOf("成交量") > -1)
                                {
                                    tblInfo.Rows[_lstFieldName.IndexOf("成交量")].Cells["Value"].Value = isEmpty ? "" : barData.Volume(iPoint).ToString("0.00");
                                    UpdateValueColor("成交量", DataTypeEnum.Volume, barData, iPoint);
                                }
                                else
                                {
                                    tblInfo.Rows.Add(new string[] { "成交量", isEmpty ? "" : barData.Volume(iPoint).ToString("0.00") });
                                    _lstFieldName.Add("成交量");
                                    UpdateValueColor("成交量", DataTypeEnum.Volume, barData, iPoint);
                                }
                                break;
                        }
                    }


                    if (_dicActiveExtraInfo.ContainsKey(strChart))
                    {
                        try
                        {
                            lstExtraInfo = _dicActiveExtraInfo[strChart];
                            _dicChartLabel[strChart].ClearText();
                            _dicChartLabel[strChart].IsUpdateText = false;
                            for (int i = 0; i < lstExtraInfo.Count; i++)
                            {
                                strLabelTitle = "";
                                barDataExtra = _dicExtraInfo[lstExtraInfo[i]];
                                lstInfo = barDataExtra.GetInfo(iPoint);

                                for (int j = 0; j < lstInfo.Count; j++)
                                {
                                    if (_lstFieldName.IndexOf(barDataExtra.GetTitle()[j]) > -1)
                                    {
                                        tblInfo.Rows[_lstFieldName.IndexOf(barDataExtra.GetTitle()[j])].Cells["Value"].Value = isEmpty
                                                                                                                                    ? ""
                                                                                                                                    : float.Parse((string)lstInfo[j]).ToString("0.00");

                                    }
                                    else
                                    {
                                        tblInfo.Rows.Add(new string[] { barDataExtra.GetTitle()[j], isEmpty ? "" : float.Parse((string)lstInfo[j]).ToString("0.00") });
                                        _lstFieldName.Add(barDataExtra.GetTitle()[j]);

                                    }

                                    labelMeta = new LabelMeta();
                                    labelMeta.ForeColor = Color.Black;
                                    labelMeta.Text = barDataExtra.GetTitle()[j] + ":" + (isEmpty
                                                                                                    ? ""
                                                                                                    : float.Parse((string)lstInfo[j]).ToString("0.00"));

                                    if (!isEmpty && ((barDataExtra.GetTitle()[j] == "A值") || (barDataExtra.GetTitle()[j] == "B值") || (barDataExtra.GetTitle()[j] == "C值")))
                                    {
                                        labelMeta.Text += (float.Parse((string)lstInfo[j]) > fClose) ? "↑" : "↓";
                                        labelMeta.ForeColor = (float.Parse((string)lstInfo[j]) > fClose) ? Color.Red : Color.Green;
                                    }

                                    if (!isEmpty && (barDataExtra.GetTitle()[j] == "3MA"))
                                    {
                                        labelMeta.Text += (f3Close < fClose) ? "↑" : "↓";
                                        labelMeta.ForeColor = (f3Close < fClose ? Color.Red : Color.Green);
                                    }

                                    if (!isEmpty && (barDataExtra.GetTitle()[j] == "6MA"))
                                    {
                                        labelMeta.Text += (f6Close < fClose) ? "↑" : "↓";
                                        labelMeta.ForeColor = (f6Close < fClose ? Color.Red : Color.Green);
                                    }

                                    if (!isEmpty && (barDataExtra.GetTitle()[j] == "18MA"))
                                    {
                                        labelMeta.Text += (f18Close < fClose) ? "↑" : "↓";
                                        labelMeta.ForeColor = (f18Close < fClose ? Color.Red : Color.Green);
                                    }

                                    if (!isEmpty && (barDataExtra.GetTitle()[j] == "72MA"))
                                    {
                                        labelMeta.Text += (f72Close < fClose) ? "↑" : "↓";
                                        labelMeta.ForeColor = (f72Close < fClose ? Color.Red : Color.Green);
                                    }

                                    _dicChartLabel[strChart].AddText(labelMeta); 

                                    strLabelTitle += "    " + barDataExtra.GetTitle()[j] + ":" + (isEmpty
                                                                                                    ? ""
                                                                                                    : float.Parse((string)lstInfo[j]).ToString("0.00"));

                                    if (!isEmpty && ((barDataExtra.GetTitle()[j] == "A值") || (barDataExtra.GetTitle()[j] == "B值") || (barDataExtra.GetTitle()[j] == "C值")))
                                        strLabelTitle += (float.Parse((string)lstInfo[j]) > fClose) ? "↑" : "↓";

                                    if (!isEmpty && (barDataExtra.GetTitle()[j] == "3MA"))
                                        strLabelTitle += (f3Close < fClose) ? "↑" : "↓";

                                    if (!isEmpty && (barDataExtra.GetTitle()[j] == "6MA"))
                                        strLabelTitle += (f6Close < fClose) ? "↑" : "↓";

                                    if (!isEmpty && (barDataExtra.GetTitle()[j] == "18MA"))
                                        strLabelTitle += (f18Close < fClose) ? "↑" : "↓";

                                    if (!isEmpty && (barDataExtra.GetTitle()[j] == "72MA"))
                                        strLabelTitle += (f72Close < fClose) ? "↑" : "↓";

                                    strLabelTitle += "  ";
                                }
                                _dicChartLabel[strChart].Text = strLabelTitle;
//                                _dicChartLabel[strChart].IsUpdateText = true;
                            }
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message + "," + ex.StackTrace);
                        }
                    }
//                    _dicChartLabel[strChart].Text = strLabelTitle;
                  _dicChartLabel[strChart].IsUpdateText = true;  
                }
*/

                lstMessage = new List<object>();
                lstMessage.Add(iPoint);
                lstMessage.Add(_dicExtraInfo);
                messageInfo = new MessageInfo();
                messageInfo.MessageTicks = DateTime.Now.Ticks;
                messageInfo.MessageSubject = "CursorPositionChanged";
                messageInfo.Message = lstMessage;
                MessageSubject.Instance().Subject.Notify(messageInfo);

            }
            catch (Exception ex)
            {
//                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
            finally
            {
                _isChangeCursorPosition = true;
            }
        }

        private void ChangeCursorPosition(double dXValue, double dYValue)
        {
            if (_isChangeCursorPosition == false)
                return;

            if (_lstFieldName == null)
                return;


            int iPoint = (int)Math.Round(dXValue, 0);
            Dictionary<string, string> dicValue;
            if (iPoint < 0)
            {
                _isChangeCursorPosition = true;
                return;
            }

            try
            {
                UpdateCursorPosition(iPoint, dYValue);
                if (OnPositionChange != null)
                {
                    dicValue = new Dictionary<string, string>();
                    for (int i = 0; i < tblInfo.RowCount; i++)
                    {
                        dicValue.Add(tblInfo.Rows[i].Cells["Field"].Value.ToString(),
                                     tblInfo.Rows[i].Cells["Value"].Value.ToString());
                    }

                    OnPositionChange(dicValue);
                }
            }
            catch (Exception ex)
            {
//                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
            finally
            {
                _isChangeCursorPosition = true;
            }
        }

        private void CursorTool_Change(object sender, Steema.TeeChart.Tools.CursorChangeEventArgs e)
        {
            ChangeCursorPosition(e.XValue, e.YValue);
        }

        private void RefreshXScale()
        {
            try
            {

                datetimeScroll.Maximum = _iTotalPointCount - _iPointPerPage;
                foreach(string strKey in _dicChartFormat.Keys)
                {
                    _dicChartFormat[strKey].XMin = datetimeScroll.Value;
                    _dicChartFormat[strKey].XMax = datetimeScroll.Value + _iPointPerPage - 1;
                }

                signalInfoPane.XMin = datetimeScroll.Value;
                signalInfoPane.XMax = datetimeScroll.Value + _iPointPerPage - 1;
                signalInfoPane.ResetXRange();

/*
                datetimeScroll.Maximum = _iTotalPointCount - _iPointPerPage;
                foreach (string strKey in _dicChart.Keys)
                {                    
                    _dicChart[strKey].Page.Current = datetimeScroll.Value;
                } 
 */ 
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        private void datetimeScroll_ValueChanged(object sender, EventArgs e)
        {
            try
            {
                RefreshXScale();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        private void splContainer_SplitterMoved(object sender, SplitterEventArgs e)
        {
            try
            {
                datetimeScroll.Width = splContainer.Panel1.Width;
                signalInfoPane.Width = splContainer.Panel1.Width;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        private void splContainer_SizeChanged(object sender, EventArgs e)
        {
            try
            {
                datetimeScroll.Width = splContainer.Panel1.Width;
                signalInfoPane.Width = splContainer.Panel1.Width;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        private void RelocationComponent()
        {
            try
            {
                signalInfoPane.Visible = IsShowLightPane;
                if (IsShowLightPane)
                {
                    signalInfoPane.Top = Height - signalInfoPane.Height;
                    datetimeScroll.Top = signalInfoPane.Top - datetimeScroll.Height;
                    splContainer.Height = Height - signalInfoPane.Height - datetimeScroll.Height;
                    btnZoomIn.Top = datetimeScroll.Top;
                    btnZoomOut.Top = datetimeScroll.Top;
                }
                else
                {
                    datetimeScroll.Top = Height - datetimeScroll.Height;
                    splContainer.Height = Height - datetimeScroll.Height;
                    btnZoomIn.Top = datetimeScroll.Top;
                    btnZoomOut.Top = datetimeScroll.Top;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        private void TeeChartPanel_Resize(object sender, EventArgs e)
        {
            try
            {
                RelocationComponent();
                datetimeScroll.Width = splContainer.Panel1.Width;
                signalInfoPane.Width = splContainer.Panel1.Width;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        private void RecalculateDistance()
        {
            int iSplitDistance;
            SplitContainer splTemp;
            SplitContainer splChartContainer;
            float fTotalHeight;

            try
            {
                fTotalHeight = 0;
                foreach (float fValue in _dicChartSize.Values)
                    fTotalHeight += fValue;
                iSplitDistance = (int)(splContainer.ClientSize.Height / fTotalHeight);

                splTemp = (SplitContainer)splContainer.Panel1.Controls[0];
                splTemp.SplitterDistance = (int)(iSplitDistance * _dicChartSize[_lstChartName[0]]);
                for (int i = 1; i < _lstChartName.Count -1 ; i++)
                {
                    splTemp = (SplitContainer)splTemp.Panel2.Controls[0];
                    splTemp.SplitterDistance = (int)(iSplitDistance * _dicChartSize[_lstChartName[i]]);
                }

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        public void Draw()
        {
            try
            {
                _lstFieldName = new List<string>();
                List<CursorTool> lstCursorTool;
                List<float> lstValue;
                List<string> lstExtraInfo;
                
                while (tblInfo.Rows.Count > 0)
                    tblInfo.Rows.RemoveAt(0);

                RecalculateDistance();

                foreach (string strChartName in _dicActiveSeries.Keys)
                {
                    _dicChartFormat[strChartName].DrawChart(_dicActiveSeries[strChartName]);
                    if(_dicHorizontalCursor.ContainsKey(strChartName))
                        _dicHorizontalCursor[strChartName].Series = _dicChart[strChartName].Series[0];
                    if(_dicVerticalCursor.ContainsKey(strChartName))
                        _dicVerticalCursor[strChartName].Series = _dicChart[strChartName].Series[0];

                    if (_dicControlLine.ContainsKey(strChartName) == false)
                        continue;

                    lstCursorTool = _dicControlLine[strChartName];
                    lstValue = _dicControlLineValue[strChartName];
                    for(int i = 0; i < lstCursorTool.Count; i++)
                    {
                        switch (lstCursorTool[i].Style)
                        {
                            case CursorToolStyles.Horizontal:
                                lstCursorTool[i].YValue = lstValue[i];
                                break;
                            case CursorToolStyles.Vertical:
                                lstCursorTool[i].XValue = lstValue[i];
                                break;
                        }
                    }
                }

                foreach(string strExtraInfo in _dicActiveExtraInfo.Keys)
                {
                    lstExtraInfo = _dicActiveExtraInfo[strExtraInfo];
                    foreach(string strExtraInfoName in lstExtraInfo)
                        foreach (string strInfo in _dicExtraInfo[strExtraInfoName].GetTitle())
                            signalInfoPane.AddActiveTitle(strInfo);
                }

                signalInfoPane.Display();
                RefreshXScale();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }



        private void btnZoomIn_Click(object sender, EventArgs e)
        {
            if (_iPointPerPage > 5)
            {
                _iPointPerPage--;
//                foreach(string strChartName in _dicChart.Keys)
//                    _dicChart[strChartName].Page.MaxPointsPerPage = _iPointPerPage;
            }
            RefreshXScale();
        }

        private void btnZoomOut_Click(object sender, EventArgs e)
        {
            if (_iPointPerPage < 300)
            {
                _iPointPerPage++;
//                foreach (string strChartName in _dicChart.Keys)
//                    _dicChart[strChartName].Page.MaxPointsPerPage = _iPointPerPage;
            }
            RefreshXScale();
        }

        public void PrintInOnSheet()
        {
            try
            {
                _memoryImage = null;
                CaptureChart();
                PrintDialog pdDialog = new PrintDialog();
                pdDialog.ShowDialog();

                PrintDocument printDocument = new PrintDocument();
                printDocument.PrinterSettings = pdDialog.PrinterSettings;
                printDocument.PrintPage += new PrintPageEventHandler(printDocument_PrintPage);
                printDocument.Print();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        public void PrintChart(string strChartName)
        {
            try
            {
                if (_dicChart.ContainsKey(strChartName) == false)
                {
                    MessageBox.Show("The Chart (" + strChartName + ") doesn't exist");
                    return;
                }

                _dicChart[strChartName].Printer.Print();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        public void PrintChartPreview(string strChartName)
        {
            try
            {
                if (_dicChart.ContainsKey(strChartName) == false)
                {
                    MessageBox.Show("The Chart (" + strChartName + ") doesn't exist");
                    return;
                }

                _dicChart[strChartName].Printer.Preview();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message + "," + ex.StackTrace);
            }
        }

        public void Dispose()
        {
            base.Dispose();

        }

        void CaptureChart()
        {
            
            Graphics mygraphics = splContainer.Panel1.CreateGraphics();
            Size s = splContainer.Panel1.Size;
            _memoryImage = new Bitmap(s.Width, s.Height, mygraphics);
            Graphics memoryGraphics = Graphics.FromImage(_memoryImage);
            IntPtr dc1 = mygraphics.GetHdc();
            IntPtr dc2 = memoryGraphics.GetHdc();
            BitBlt(dc2, 0, 0, splContainer.Panel1.ClientRectangle.Width, splContainer.Panel1.ClientRectangle.Height, dc1, 0, 0, 13369376);
            mygraphics.ReleaseHdc(dc1);
            memoryGraphics.ReleaseHdc(dc2);

        }

        void printDocument_PrintPage(object sender, PrintPageEventArgs e)
        {
            if (_memoryImage == null)
                return;

            e.Graphics.DrawImage(_memoryImage, e.PageBounds);
        }


        #region IObserver Members

        public void Update(object oSource, IMessageInfo miMessage)
        {
            
        }

        #endregion
    }
}
